package com.service.Authorization.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.service.Authorization.dao.ManageProgrammeInfoDao;
import com.service.Authorization.dao.ProgrammeButtonDao;
import com.service.Authorization.dao.ProgrammePasswordLayoutDao;
import com.service.Authorization.dao.QyCorpInfoDao;
import com.service.Authorization.dto.*;
import com.service.Authorization.entity.*;
import com.service.Authorization.service.*;
import com.service.Authorization.util.AESCBCUtil;
import com.service.Authorization.vo.*;
import com.service.config.constant.Constant;
import com.service.config.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.service.config.constant.Constant.*;
import static com.service.config.utils.CharUtil.getCharAndNumr;

/**
 * (QyCorpInfo)表服务实现类
 *
 * @author makejava
 * @since 2021-09-09 15:42:01
 */
@Slf4j
@Service("qyCorpInfoService")
public class QyCorpInfoServiceImpl implements QyCorpInfoService {
    @Resource
    private QyCorpInfoDao qyCorpInfoDao;
    @Resource
    private UserAuthLogService userAuthLogService;
    @Value("${spring.fileSeverDomain}")
    private String fileSeverDomain;
    @Value("${spring.nginxUrl}")
    private String nginxUrl;
    @Resource
    private ManageProgrammeInfoDao manageProgrammeInfoDao;
    /**
     * 服务对象
     */
    @Resource
    private QyProgrammeApiBindService qyProgrammeApiBindService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ProgrammePasswordLayoutDao programmePasswordLayoutDao;
    @Resource
    private ProgrammeButtonDao programmeButtonDao;
    @Resource
    private ProgrammeInfoExamineService programmeInfoExamineService;
    @Resource
    private QueryWeiChatServiceImpl queryWeiChatService;
    @Resource
    private PortalUserService portalUserService;
    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public QyCorpInfo queryById(String id) {
        return this.qyCorpInfoDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<QyCorpInfo> queryAllByLimit(int offset, int limit) {
        return this.qyCorpInfoDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param qyCorpInfo 实例对象
     * @return 实例对象
     */
    @Override
    public QyCorpInfo insert(QyCorpInfo qyCorpInfo) {
        this.qyCorpInfoDao.insert(qyCorpInfo);
        return qyCorpInfo;
    }

    /**
     * 修改数据
     *
     * @param qyCorpInfo 实例对象
     * @return 实例对象
     */
    @Override
    public QyCorpInfo update(QyCorpInfo qyCorpInfo) {
        this.qyCorpInfoDao.update(qyCorpInfo);
        return this.queryById(qyCorpInfo.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String id) {
        return this.qyCorpInfoDao.deleteById(id) > 0;
    }

    /**
     * 用户查询已经配置的企业信息
     * @param userId
     * @return
     */
    @Override
    public Result queryByUserId(String userId, Integer type) {
        QyCorpInfo qyCorpInfo = new QyCorpInfo();
        qyCorpInfo.setManageId(userId);
        qyCorpInfo.setType(type);
        List<QyCorpInfo> qyCorpInfoList = qyCorpInfoDao.queryAll(qyCorpInfo);
        if (qyCorpInfoList != null && qyCorpInfoList.size() > 0 ) {
            HashMap map = new HashMap();
            List<QyCorpInfoDto> qyCorpInfoDtoList = ModelMapperUtil.strictMapList(qyCorpInfoList, QyCorpInfoDto.class);
            if (type != null) {
                if (type==0) {
                    map.put("isQy", qyCorpInfoDtoList.stream().filter(qyCorpInfoDto -> qyCorpInfoDto.getType().equals(0)).collect(Collectors.toList()));
                }else {
                    map.put("isMini", qyCorpInfoDtoList.stream().filter(qyCorpInfoDto -> qyCorpInfoDto.getType().equals(1)).collect(Collectors.toList()));
                }
            }
            else {
                map.put("isQy", qyCorpInfoDtoList.stream().filter(qyCorpInfoDto -> qyCorpInfoDto.getType().equals(0)).collect(Collectors.toList()));
                map.put("isMini", qyCorpInfoDtoList.stream().filter(qyCorpInfoDto -> qyCorpInfoDto.getType().equals(1)).collect(Collectors.toList()));
            }
            return  Result.ok().setData(map);
        }
        return Result.failure(Constant.QY_NOT_CONFIG,Constant.QY_NOT_CONFIG_DESC);
    }

    /**
     * 新增企业信息
     * @param addQyCorpInfoDto
     * @param userDto
     * @return
     */
    @Override
    @Transactional
    public Result addQyCorpInfo(AddQyCorpInfoDto addQyCorpInfoDto, UserDto userDto) {
        QyCorpInfo qyCorpInfo = ModelMapperUtil.strictMap(addQyCorpInfoDto, QyCorpInfo.class);
        qyCorpInfo.setCpAddTime(new Date());
        qyCorpInfo.setId(IdUtil.getStringId());
        qyCorpInfo.setManageId(userDto.getId());
        qyCorpInfo.setCpAdder(userDto.getUsername());
        qyCorpInfo.setCpUpdater(userDto.getUsername());
        qyCorpInfo.setCpUpdateTime(new Date());
        qyCorpInfo.setCpAddTime(new Date());
        qyCorpInfo.setUrlNumber(verGetCharAndNumber(16));
        int insert = qyCorpInfoDao.insert(qyCorpInfo);
        if (insert > 0) {
            return Result.ok();
        }
        return Result.failure("新增失败，请检查");
    }

    /**
     * 更新企业信息
     * @param updateQyCorpInfoDto
     * @return
     */
    @Override
    @Transactional
    public Result updateQyCorpInfo(UpdateQyCorpInfoDto updateQyCorpInfoDto) {
        QyCorpInfo qyCorpInfo = ModelMapperUtil.strictMap(updateQyCorpInfoDto, QyCorpInfo.class);
        qyCorpInfo.setCpUpdateTime(new Date());
        int update = qyCorpInfoDao.update(qyCorpInfo);
        if (update > 0) {
            return Result.ok();
        }
        return Result.failure("修改失败，请检查");
    }

    /**
     * 刷新url页面时拼接的参数
     * @param qyCorpInfoId
     * @return
     */
    @Override
    @Transactional
    public Result freshQyCorpInfo(String qyCorpInfoId) {
        QyCorpInfo qyCorpInfo = new QyCorpInfo();
        qyCorpInfo.setId(qyCorpInfoId);
        qyCorpInfo.setUrlNumber(verGetCharAndNumber(16));
        int update = qyCorpInfoDao.update(qyCorpInfo);
        QyProgrammeApiBind qyProgrammeApiBind = new QyProgrammeApiBind();
        qyProgrammeApiBind.setCorpInfoId(qyCorpInfoId);
        List<QyProgrammeApiBind> qyProgrammeApiBindList = qyProgrammeApiBindService.queryAll(qyProgrammeApiBind);
        qyProgrammeApiBindList.forEach(qyProgrammeApiBind1 -> {
            String onlyUrl = qyProgrammeApiBind1.getOnlyUrl();
            String[] split = onlyUrl.split("&number=");
            onlyUrl = split[0].concat("&number=").concat(qyCorpInfo.getUrlNumber());
            qyProgrammeApiBind1.setOnlyUrl(onlyUrl);
        });
        qyProgrammeApiBindService.insertBatch(qyProgrammeApiBindList);
        if (update > 0) {
            return Result.ok();
        }
        return Result.failure("修改失败，请检查");
    }

    /**
     * 批量绑定方案和api
     * @param qyProgrammeApiBindList
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public Result QyCorpInfoBindApi(List<QyProgrammeApiBind> qyProgrammeApiBindList,String userId) {
        qyProgrammeApiBindService.deleteById(qyProgrammeApiBindList.get(0).getProgrammeInfoId());
        qyProgrammeApiBindList.forEach(qyProgrammeApiBind1 -> {
            qyProgrammeApiBind1.setBindTime(new Date()) ;
            qyProgrammeApiBind1.setManageId(userId);
        });
        if (qyProgrammeApiBindList.size() > 0) {
            int insertBatch = qyProgrammeApiBindService.insertBatch(qyProgrammeApiBindList);
            if (insertBatch > 0) {
                return Result.ok();
            }
        }
        return Result.failure("批量绑定方案和api失败，请检查");
    }

    /**
     * 解除绑定
     * @param qyCorpInfoVo
     * @return
     */
    @Override
    public Result cancelQyCorpInfoBindApi(QyCorpInfoVo qyCorpInfoVo) {
        int delete = qyProgrammeApiBindService.cancelQyCorpInfoBindApi(qyCorpInfoVo);
        if (delete > 0) {
            return Result.ok();
        }
        return Result.failure("删除失败，请检查");
    }

    @Override
    public Result getQyCorpInfoDetails(String userId, String qyCorpInfoId) {
        List<ScreenUserDto> screenUserDtoList = portalUserService.queryAll(userId);
        QyCorpInfo qyCorpInfo = new QyCorpInfo();
        qyCorpInfo.setManageId(userId);
        List<QyCorpInfo> qyCorpInfoList = qyCorpInfoDao.queryAll(qyCorpInfo);
        QyProgrammeApiBind qyProgrammeApiBind = new QyProgrammeApiBind();
        qyProgrammeApiBind.setManageId(userId);
        qyProgrammeApiBind.setProgrammeInfoId(qyCorpInfoId);
        List<QyProgrammeApiBind> qyProgrammeApiBindList = qyProgrammeApiBindService.queryAll(qyProgrammeApiBind);
        List<BindQyCorpInfoVo> qyCorpInfoVos = ModelMapperUtil.strictMapList(qyProgrammeApiBindList, BindQyCorpInfoVo.class);
        if (qyProgrammeApiBindList.size() > 0) {
            qyCorpInfoVos.forEach(qyCorpInfoVo -> {
                List<QyCorpInfo> collect = qyCorpInfoList.stream().filter(qyCorpInfo1 -> qyCorpInfo1.getId().equals(qyCorpInfoVo.getCorpInfoId())).collect(Collectors.toList());
                if (collect.size() > 0) {
                    if (collect.get(0).getType()==0) {
                        qyCorpInfoVo.setOnlyUrl(fileSeverDomain.concat(nginxUrl).concat("/enterprise?programmeInfoId=")
                                .concat(qyCorpInfoVo.getProgrammeInfoId()).concat("&portalUserId=")
                                .concat(qyCorpInfoVo.getPortalUserId()).concat("&number=").concat(collect.get(0).getUrlNumber()));
                    }else {
                        qyCorpInfoVo.setOnlyUrl(fileSeverDomain.concat(nginxUrl).concat("/weChat?programmeInfoId=")
                                .concat(qyCorpInfoVo.getProgrammeInfoId()).concat("&portalUserId=")
                                .concat(qyCorpInfoVo.getPortalUserId()).concat("&number=").concat(collect.get(0).getUrlNumber()));
                    }
                    qyCorpInfoVo.setCpName(collect.get(0).getCpName());
                }
                List<ScreenUserDto> collect1 = screenUserDtoList.stream().filter(screenUserDto -> screenUserDto.getId().equals(qyCorpInfoVo.getPortalUserId())).collect(Collectors.toList());
                boolean present = collect1.stream().findFirst().isPresent();
                if (present) {
                    qyCorpInfoVo.setScreenUserDto(collect1.stream().findFirst().get());
                }
            });
            qyProgrammeApiBindList = ModelMapperUtil.strictMapList(qyCorpInfoVos, QyProgrammeApiBind.class);
            updateBatch(qyProgrammeApiBindList);
            return Result.ok().setData(qyCorpInfoVos);
        }
        return Result.failure("企业还未绑定方案，请前往绑定页面");
    }

    @Async
    public void updateBatch(List<QyProgrammeApiBind> qyProgrammeApiBindList) {
        qyProgrammeApiBindList.stream().forEach(qyProgrammeApiBind -> {
            qyProgrammeApiBindService.update1(qyProgrammeApiBind);
        });
    }

    /**
     * 检测员工身份以及授权员工使用该网络
     * @param bAuthToken
     * @param secretAndCode
     * @return
     * @throws Exception
     */
    @Override
    public Result checkQyWeiUser(String bAuthToken, SecretAndCode secretAndCode) throws Exception {
        if (bAuthToken != null && !bAuthToken.equals("")) {
            if (!redisUtil.exist(bAuthToken) ) {
                if (redisUtil.exist(secretAndCode.getSecret())) {
                    String value = redisUtil.getValue(secretAndCode.getSecret());
                    AuthorizationVo authorizationVo = JsonXMLUtils.json2obj(value, AuthorizationVo.class);
                    authorizationVo.setCode(secretAndCode.getCode());
                    return getResult(bAuthToken,authorizationVo);
                }
                return Result.failure(PARAMETER_NOT_FOUND,"参数已失效，请重新获取");
            }
            if (!redisUtil.exist(secretAndCode.getSecret())) {
                return Result.failure(PARAMETER_NOT_FOUND,"参数已失效，请重新获取");
            }
            String value = redisUtil.getValue(secretAndCode.getSecret());
            AuthorizationVo authorizationVo = JsonXMLUtils.json2obj(value, AuthorizationVo.class);
            authorizationVo.setCode(secretAndCode.getCode());
            QyWeiChatUserDetailVo qyWeiChatUserDetailVo = JsonXMLUtils.json2obj(redisUtil.getValue(bAuthToken), QyWeiChatUserDetailVo.class);
            if (qyWeiChatUserDetailVo.getUserid() != null) {
                QyCorpInfo qyCorpInfo = qyCorpInfoDao.queryByNumber(authorizationVo.getNumber());
                Result auth = auth(qyWeiChatUserDetailVo, authorizationVo, qyCorpInfo);
                if (auth.getCode() == 200) {
                    Map map = new HashMap();
                    redisUtil.set(bAuthToken,4,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),2);
                    //认证结果
                    redisUtil.set(authorizationVo.getApmac().concat(authorizationVo.getUmac()).concat(authorizationVo.getSsid()).concat("auth"),1,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),10);
                    map.put("token",bAuthToken);
                    return Result.ok().setData(map);
                }
                return auth;
            }
            QyCorpInfo qyCorpInfo = qyCorpInfoDao.queryByNumber(authorizationVo.getNumber());
            //访客突然成为企业微信的员工则需要查询其身份并授权
            insertAuthorizationUser(new UserAuthLog(),qyWeiChatUserDetailVo,authorizationVo,qyCorpInfo);
            redisUtil.set(bAuthToken,4,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),2);
            //认证结果
            redisUtil.set(authorizationVo.getApmac().concat(authorizationVo.getUmac()).concat(authorizationVo.getSsid()).concat("auth"),1,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),10);
            return Result.failure("你不是该企业的员工");
        }else {
            bAuthToken = UserTokenManager.generateToken(secretAndCode.getCode());// 新增用户
            if (!redisUtil.exist(secretAndCode.getSecret())) {
                return Result.failure(PARAMETER_NOT_FOUND,"参数已失效，请重新获取");
            }
            String value = redisUtil.getValue(secretAndCode.getSecret());
            AuthorizationVo authorizationVo = JsonXMLUtils.json2obj(value, AuthorizationVo.class);
            authorizationVo.setCode(secretAndCode.getCode());
            return getResult(bAuthToken, authorizationVo);
        }

    }

    private Result getResult(String bAuthToken, AuthorizationVo authorizationVo) throws Exception {
        if (authorizationVo.getNumber() == null || authorizationVo.getNumber().equals("")) {
            return Result.failure(PARAMETER_NOT_FOUND,parameterNotFound); // 参数错误
        }
        QyCorpInfo qyCorpInfo = qyCorpInfoDao.queryByNumber(authorizationVo.getNumber());
        if (qyCorpInfo == null) {
            return Result.failure(QY_NOT_CONFIG,QY_NOT_CONFIG_DESC); // 参数错误
        }
        String url = queryWeiChatService.getUrl("", qyCorpInfo.getCorpId(), qyCorpInfo.getSecret());
        HashMap openId = queryWeiChatService.getOpenId(url);
        if (openId.containsKey("errcode")) {
            return Result.ok().setData(openId);
        }
        Object weiChatDto1 = openId.get("weiChatDto");
        Map<String, Object> map2 = JsonXMLUtils.json2map(weiChatDto1.toString());
        WeiChatVo weiChatVo = ModelMapperUtil.strictMap(map2, WeiChatVo.class);
        openId = queryWeiChatService.getUserInfo(weiChatVo.getAccess_token(), authorizationVo.getCode());
        if (openId.containsKey("errcode")){
            return Result.ok().setData(openId);
        }
        weiChatDto1 = openId.get("qyWeiChatUserVo");
        map2 = JsonXMLUtils.json2map(weiChatDto1.toString());
        QyWeiChatUserVo qyWeiChatUserVo1 = ModelMapperUtil.strictMap(map2, QyWeiChatUserVo.class);
        if (qyWeiChatUserVo1.getUserid() != null) {
            openId = queryWeiChatService.getUser(weiChatVo.getAccess_token(), qyWeiChatUserVo1.getUserid());
            if (openId.containsKey("errcode")){
                return Result.ok().setData(openId);
            }
            weiChatDto1 = openId.get("qyWeiChatUserDetailVo");
            map2 = JsonXMLUtils.json2map(weiChatDto1.toString());
            QyWeiChatUserDetailVo qyWeiChatUserDetailVo = ModelMapperUtil.strictMap(map2, QyWeiChatUserDetailVo.class);
            qyWeiChatUserDetailVo.setAccess_token(weiChatVo.getAccess_token());
            qyWeiChatUserDetailVo.setDeviceId("1");
            qyWeiChatUserDetailVo.setStatus(true);
            qyWeiChatUserDetailVo.setQyCorpInfoId(qyCorpInfo.getId());
            qyWeiChatUserDetailVo.setPortalUserId(authorizationVo.getPortalUserId());
            Result auth = auth(qyWeiChatUserDetailVo, authorizationVo, qyCorpInfo);
            if (auth.getCode() == 200) {
                Map map = new HashMap();
                redisUtil.set(bAuthToken,4,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),2);
                //认证结果
                redisUtil.set(authorizationVo.getApmac().concat(authorizationVo.getUmac()).concat(authorizationVo.getSsid()).concat("auth"),1,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),10);
                map.put("token",bAuthToken);
                return Result.ok().setData(map);
            }
            return auth;
        } else {
            QyWeiChatUserDetailVo qyWeiChatUserDetailVo = new QyWeiChatUserDetailVo();
            qyWeiChatUserDetailVo.setStatus(false);
            qyWeiChatUserDetailVo.setDeviceId("2");
            qyWeiChatUserDetailVo.setName("非企业员工");
            insertAuthorizationUser(new UserAuthLog(),qyWeiChatUserDetailVo,authorizationVo,qyCorpInfo);
            //认证结果
            redisUtil.set(authorizationVo.getApmac().concat(authorizationVo.getUmac()).concat(authorizationVo.getSsid()).concat("auth"),1,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),10);
            return Result.failure("你不是该企业的员工");
        }
    }

    /**
     * 无密码方案
     * @param authorizationVo
     * @return
     */
    private Result auth(QyWeiChatUserDetailVo qyWeiChatUserDetailVo, AuthorizationVo authorizationVo,QyCorpInfo qyCorpInfo) throws Exception {
        if (authorizationVo.getPortalUserId() == null) {
            return Result.failure(PARAMETER_NOT_FOUND,parameterNotFound); // 参数错误
        }
        QyProgrammeApiBind qyCorpInfoBindApi = qyProgrammeApiBindService.find(authorizationVo.getProgrammeInfoId(),qyCorpInfo.getManageId(),qyCorpInfo.getId());
        PortalUser portalUser = portalUserService.queryById(qyCorpInfoBindApi.getPortalUserId());
        if (portalUser == null) {
            return Result.failure(AUTH_FLAIRE,AUTH_FLAIRE_DESC); //认证失败
        }
        String auth = auth(portalUser.getTenantName(), portalUser.getTenantPwd(), portalUser.getDomain(), authorizationVo);// 认证授权
        if (auth == null) {
            qyWeiChatUserDetailVo.setStatus(false);
            insertAuthorizationUser(new UserAuthLog(),qyWeiChatUserDetailVo,authorizationVo,qyCorpInfo);
            return Result.failure(AUTH_FLAIRE,AUTH_FLAIRE_DESC); //认证失败
        }
        redisUtil.set(authorizationVo.getApmac().concat(authorizationVo.getUmac()).concat(authorizationVo.getSsid()).concat("auth"),1,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),10);
        insertAuthorizationUser(new UserAuthLog(),qyWeiChatUserDetailVo,authorizationVo,qyCorpInfo);
        return Result.ok();
    }

    /**
     * 认证日志列表
     * @param qyWeiChatUserDetailVo
     * @param authorizationVo
     * @param qyCorpInfo
     */
    private void insertAuthorizationUser(UserAuthLog userAuthLog,QyWeiChatUserDetailVo qyWeiChatUserDetailVo, AuthorizationVo authorizationVo,QyCorpInfo qyCorpInfo) throws Exception {
        userAuthLog.setId(IdUtil.getStringId());
        userAuthLog.setAuthTime(new Date());
        userAuthLog.setCorpId(qyCorpInfo.getCorpId());
        userAuthLog.setCorpInfoId(qyCorpInfo.getId());
        userAuthLog.setUserId(qyWeiChatUserDetailVo.getUserid());
        userAuthLog.setOpenId(qyWeiChatUserDetailVo.getOpenId());
        userAuthLog.setUserName(qyWeiChatUserDetailVo.getName());
        userAuthLog.setApMac(authorizationVo.getApmac());
        userAuthLog.setSsid(authorizationVo.getSsid());
        userAuthLog.setSiteId(authorizationVo.getSiteId());
        if (qyWeiChatUserDetailVo.getOpenId() == null) {
            userAuthLog.setOpenId("1");
        }
        userAuthLog.setPortalUserId(authorizationVo.getPortalUserId());
        userAuthLog.setNodeIp(authorizationVo.getNodeIp());
        userAuthLog.setTerminalIp(authorizationVo.getUaddress());
        userAuthLog.setStatus(qyWeiChatUserDetailVo.getStatus());
        userAuthLog.setTerminalMac(authorizationVo.getUmac());
        userAuthLog.setProgrammeInfoId(authorizationVo.getProgrammeInfoId());
        userAuthLogService.insert(userAuthLog);
    }

    @Override
    public Result getHtml(AuthorizationVo authorizationVo) throws Exception {
        ManageProgrammeInfo manageProgrammeInfo = manageProgrammeInfoDao.queryById(authorizationVo.getProgrammeInfoId());
        if (manageProgrammeInfo != null) {
            if (manageProgrammeInfo.getProgrammeType() == 1) {
                QyCorpInfo qyCorpInfo = qyCorpInfoDao.queryByNumber(authorizationVo.getNumber());
                ProgrammeInfoExamineVo programmeInfoExamineVo = ModelMapperUtil.strictMap(manageProgrammeInfo, ProgrammeInfoExamineVo.class);
                programmeInfoExamineVo.setComment(JSONArray.parseArray(manageProgrammeInfo.getComment()).toJavaList(AssemblyInfoDto.class));
                ProgrammeButton programmeButton = new ProgrammeButton();
                programmeButton.setProgrammeId(programmeInfoExamineVo.getId());
                programmeButton.setManageId(manageProgrammeInfo.getManageId());
                List<ProgrammeButton> programmeButtons = programmeButtonDao.queryAll(programmeButton);
                programmeInfoExamineVo.setPassword(false);
                programmeInfoExamineVo.setQywxUrl(qyCorpInfo.getQywxUrl());
                programmeInfoExamineVo.setProgrammeType(manageProgrammeInfo.getProgrammeType());
                if (programmeButtons.size() > 0) {
                    programmeInfoExamineVo.setProgrammeButton(JsonXMLUtils.json2obj(JsonXMLUtils.obj2json(programmeButtons.get(0)), ProgrammeButtonDto.class));
                }
                String secret = getSecret(16);
                Map map = new HashMap();
                map.put("secret",secret);
                redisUtil.set(secret,1,JsonXMLUtils.obj2json(authorizationVo),3);
                map.put("programmeInfoExamineVo",programmeInfoExamineVo);
                return Result.ok().setData(map);
            }
            return Result.failure("方案不属于企业独有,请重新配置");
        }
        return Result.failure("方案不存在");
    }

    /**
     * 页面查询认证结果
     * @param apmac
     * @param umac
     * @param ssid
     * @return
     * @throws Exception
     */
    @Override
    public Result checkQyWeiUser(String apmac, String umac, String ssid) throws Exception {
        String key = apmac.concat(umac).concat(ssid).concat("auth");
        if (redisUtil.exist(key)){
            QyWeiChatUserDetailVo qyWeiChatUserDetailVo = JsonXMLUtils.json2obj(redisUtil.getValue(key), QyWeiChatUserDetailVo.class);
            if (qyWeiChatUserDetailVo.getUserid() != null) {
                return Result.ok();
            }else {
                return Result.failure("拒绝");
            }
        }
        return Result.failure(AUTH_WAIT,AUTH_WAIT_DESC);
    }

    @Override
    public Result deleteQyCorpInfo(String userId, String qyCorpInfoId) {
        qyCorpInfoDao.deleteById(qyCorpInfoId);
        qyProgrammeApiBindService.deleteByQyCorpInfoId(qyCorpInfoId,userId);
        return Result.ok();
    }

    @Override
    public Result FindQyCorpInfoBindApi(String programmeId, String userId) {
        QyProgrammeApiBind apiBind = new  QyProgrammeApiBind();
        apiBind.setManageId(userId);
        apiBind.setProgrammeInfoId(programmeId);
        List<QyProgrammeApiBind> qyProgrammeApiBindList = qyProgrammeApiBindService.queryAll(apiBind);
        if (qyProgrammeApiBindList.size() > 0) {
            boolean b = qyProgrammeApiBindList.stream().allMatch(qyProgrammeApiBind -> qyProgrammeApiBind.getCorpInfoId() == null || qyProgrammeApiBind.getPortalUserId() == null);
            if (b) {
                return Result.failure("方案不存在");
            }
            return Result.ok();
        }
        return Result.failure("方案不存在");
    }

    @Override
    public Result getSecret(AuthorizationVo authorizationVo) throws Exception {
        String secret = getSecret(16);
        Map map = new HashMap();
        map.put("secret",secret);
        redisUtil.set(secret,1,JsonXMLUtils.obj2json(authorizationVo),3);
        return Result.ok().setData(map);
    }

    /**
     * 微信小程序页面获取
     * @param number
     * @param programmeId
     * @return
     * @throws Exception
     */
    @Override
    public Result getWeiChatHtml(String number, String programmeId) throws Exception {
        ManageProgrammeInfo manageProgrammeInfo = manageProgrammeInfoDao.queryById(programmeId);
        if (manageProgrammeInfo != null) {
            if (manageProgrammeInfo.getProgrammeType() == 2) {
                QyCorpInfo qyCorpInfo = qyCorpInfoDao.queryByNumber(number);
                ProgrammeInfoExamineVo programmeInfoExamineVo = ModelMapperUtil.strictMap(manageProgrammeInfo, ProgrammeInfoExamineVo.class);
                programmeInfoExamineVo.setComment(JSONArray.parseArray(manageProgrammeInfo.getComment()).toJavaList(AssemblyInfoDto.class));
                ProgrammeButton programmeButton = new ProgrammeButton();
                programmeButton.setProgrammeId(programmeInfoExamineVo.getId());
                programmeButton.setManageId(manageProgrammeInfo.getManageId());
                List<ProgrammeButton> programmeButtons = programmeButtonDao.queryAll(programmeButton);
                programmeInfoExamineVo.setPassword(false);
                programmeInfoExamineVo.setQywxUrl(qyCorpInfo.getQywxUrl());
                programmeInfoExamineVo.setProgrammeType(manageProgrammeInfo.getProgrammeType());
                if (programmeButtons.size() > 0) {
                    programmeInfoExamineVo.setProgrammeButton(JsonXMLUtils.json2obj(JsonXMLUtils.obj2json(programmeButtons.get(0)), ProgrammeButtonDto.class));
                }
                return Result.ok().setData(programmeInfoExamineVo);
            }
            return Result.failure("方案不属于微信小程序独有,请重新配置");
        }
        return Result.failure("方案不存在");
    }

    /**
     * 微信小程序校验身份
     * @param bAuthToken
     * @param authorizationVo
     * @return
     * @throws Exception
     */
    @Override
    public Result checkQyWeChatUser(String bAuthToken, AuthorizationVo authorizationVo) throws Exception {
        log.info("JsonXMLUtils.obj2json(authorizationVo):"+JsonXMLUtils.obj2json(authorizationVo));
        if (bAuthToken != null && !bAuthToken.equals("")) {
            if (!redisUtil.exist(bAuthToken) ) {
                return getWechatResult(bAuthToken,authorizationVo);
            }
            QyWeiChatUserDetailVo qyWeiChatUserDetailVo = JsonXMLUtils.json2obj(redisUtil.getValue(bAuthToken), QyWeiChatUserDetailVo.class);
            QyCorpInfo qyCorpInfo = qyCorpInfoDao.queryByNumber(authorizationVo.getNumber());
            if (qyCorpInfo == null) {
                return Result.failure("未查到微信小程序信息");
            }
            Result auth = auth(qyWeiChatUserDetailVo, authorizationVo, qyCorpInfo);
            if (auth.getCode() == 200) {
                Map map = new HashMap();
                redisUtil.set(bAuthToken,4,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),2);
                //认证结果
                map.put("token",bAuthToken);
                return Result.ok().setData(map);
            }
            return auth;
        }else {
            bAuthToken = UserTokenManager.generateToken(authorizationVo.getCode());// 新增用户
            return getWechatResult(bAuthToken, authorizationVo);
        }

    }

    /**
     *  获取小程序 scheme 码
     * @param authorizationVo
     * @return
     * @throws Exception
     */
    @Override
    public Result getUrlScheme(AuthorizationVo authorizationVo) throws Exception {
        if (authorizationVo.getNumber() == null || authorizationVo.getNumber().equals("")) {
            return Result.failure(PARAMETER_NOT_FOUND,parameterNotFound); // 参数错误
        }
        QyCorpInfo qyCorpInfo = qyCorpInfoDao.queryByNumber(authorizationVo.getNumber());
        if (qyCorpInfo == null) {
            return Result.failure(QY_NOT_CONFIG,QY_NOT_CONFIG_DESC); // 参数错误
        }
        if (qyCorpInfo.getAppId() == null || qyCorpInfo.getAppId().equals("")|| qyCorpInfo.getAppletSecret() == null || qyCorpInfo.getAppletSecret().equals("")) {
            return Result.failure(PARAMETER_NOT_FOUND,parameterNotFound); // 参数错误
        }
        /**
         * 是否存在token
         */
       if (redisUtil.exist(qyCorpInfo.getAppId().concat(":").concat(qyCorpInfo.getAppletSecret()))) {
           String token = redisUtil.getValue(qyCorpInfo.getAppId().concat(":").concat(qyCorpInfo.getAppletSecret()));
           Map<String, Object> urlSchemeGenerate = queryWeiChatService.getUrlSchemeGenerate(token, authorizationVo);
           if (urlSchemeGenerate.containsKey("errcode")) {
               return Result.ok().setData(urlSchemeGenerate);
           }
           Object weiChatResponseDto = urlSchemeGenerate.get("weiChatResponseDto");
           Map<String, Object> stringObjectMap = JsonXMLUtils.json2map(weiChatResponseDto.toString());
           WeiChatResponseDto weiChatResponseDto1 = ModelMapperUtil.strictMap(stringObjectMap, WeiChatResponseDto.class);
           return Result.ok().setData(weiChatResponseDto1.getOpenlink());
       }
        String url = queryWeiChatService.getUrlWenXinAccessToken("", qyCorpInfo.getAppId(), qyCorpInfo.getAppletSecret());
        HashMap wenXinAccessToken = queryWeiChatService.getWenXinAccessToken(url);
        if (wenXinAccessToken.containsKey("errcode")) {
            return Result.ok().setData(wenXinAccessToken);
        }
        Object weiChatDto1 = wenXinAccessToken.get("weiChatVo");
        Map<String, Object> map2 = JsonXMLUtils.json2map(weiChatDto1.toString());
        WeiChatVo weiChatVo = ModelMapperUtil.strictMap(map2, WeiChatVo.class);
        redisUtil.set(qyCorpInfo.getAppId().concat(":").concat(qyCorpInfo.getAppletSecret()),4,weiChatVo.getAccess_token(),2);
        Map<String, Object> urlSchemeGenerate = queryWeiChatService.getUrlSchemeGenerate(weiChatVo.getAccess_token(), authorizationVo);
        if (urlSchemeGenerate.containsKey("errcode")) {
            return Result.ok().setData(urlSchemeGenerate);
        }
        Object weiChatResponseDto = urlSchemeGenerate.get("weiChatResponseDto");
        map2 = JsonXMLUtils.json2map(weiChatResponseDto.toString());
        WeiChatResponseDto weiChatResponseDto1 = ModelMapperUtil.strictMap(map2, WeiChatResponseDto.class);
        return Result.ok().setData(weiChatResponseDto1.getOpenlink());
    }

    private Result getWechatResult(String bAuthToken, AuthorizationVo authorizationVo) throws Exception {
        if (authorizationVo.getNumber() == null || authorizationVo.getNumber().equals("")) {
            return Result.failure(PARAMETER_NOT_FOUND,parameterNotFound); // 参数错误
        }
        QyCorpInfo qyCorpInfo = qyCorpInfoDao.queryByNumber(authorizationVo.getNumber());
        if (qyCorpInfo == null) {
            return Result.failure(QY_NOT_CONFIG,QY_NOT_CONFIG_DESC); // 参数错误
        }
        if (qyCorpInfo.getAppId() == null ||qyCorpInfo.getAppId().equals("")||qyCorpInfo.getAppletSecret().equals("")|| qyCorpInfo.getAppletSecret() == null) {
            return Result.failure(QY_NOT_CONFIG,QY_NOT_CONFIG_DESC); // 参数错误
        }
        String url = queryWeiChatService.getUrlWenXin("", qyCorpInfo.getAppId(), qyCorpInfo.getAppletSecret(),authorizationVo.getCode());
        HashMap openId = queryWeiChatService.getWeChatOpenId(url);
        if (openId.containsKey("errcode")) {
            return Result.ok().setData(openId);
        }
        Object weiChatDto1 = openId.get("weiChatDto");
        Map<String, Object> map2 = JsonXMLUtils.json2map(weiChatDto1.toString());
        WeiChatDto weiChatDto = ModelMapperUtil.strictMap(map2, WeiChatDto.class);
        QyWeiChatUserDetailVo qyWeiChatUserDetailVo = ModelMapperUtil.strictMap(map2, QyWeiChatUserDetailVo.class);
        qyWeiChatUserDetailVo.setOpenId(weiChatDto.getOpenid());
        qyWeiChatUserDetailVo.setDeviceId("1");
        qyWeiChatUserDetailVo.setStatus(true);
        qyWeiChatUserDetailVo.setQyCorpInfoId(qyCorpInfo.getId());
        qyWeiChatUserDetailVo.setPortalUserId(authorizationVo.getPortalUserId());
        UserAuthLog userAuthLog = new UserAuthLog();
        if (authorizationVo.getEncryptedData() != null && !"".equals(authorizationVo.getEncryptedData()) &&authorizationVo.getIv() != null && !"".equals(authorizationVo.getIv())){
            try{
                String decrypt = AESCBCUtil.decrypt(authorizationVo.getEncryptedData(), weiChatDto.getSession_key(), authorizationVo.getIv(), "UTF-8");
                WeiChatPhoneNumberDto weiChatPhoneNumberDto = JsonXMLUtils.json2obj(decrypt, WeiChatPhoneNumberDto.class);
                if (weiChatPhoneNumberDto != null) {
                    if (weiChatPhoneNumberDto.getPhoneNumber() != null) {

                        userAuthLog.setTelPhone(weiChatPhoneNumberDto.getPhoneNumber());
                    }
                    if (weiChatPhoneNumberDto.getPurePhoneNumber() != null) {
                        userAuthLog.setTelPhone(weiChatPhoneNumberDto.getPurePhoneNumber());
                    }
                }
            }catch (Exception e){
                log.error("解析错误"+weiChatDto.getOpenid());
                userAuthLog.setTelPhone(null);
            }
        }
        Result auth = auth(qyWeiChatUserDetailVo, authorizationVo, qyCorpInfo);
        if (auth.getCode() == 200) {
            Map map = new HashMap();
            redisUtil.set(bAuthToken,4,JsonXMLUtils.obj2json(qyWeiChatUserDetailVo),2);
            map.put("token",bAuthToken);
            return Result.ok().setData(map);
        }
        return auth;
}

    private String getSecret(int i) {
        String charAndNumber = getCharAndNumr(i);
        if (redisUtil.exist(charAndNumber)) {
            getSecret(i);
        }
        return charAndNumber;
    }

    private String verGetCharAndNumber(int i) {
        QyCorpInfo qyCorpInfo = new QyCorpInfo();
        qyCorpInfo.setUrlNumber(getCharAndNumr(i));
        List<QyCorpInfo> qyCorpInfoList = qyCorpInfoDao.queryAll(qyCorpInfo);
        if (qyCorpInfoList.size() > 0) {
            verGetCharAndNumber(i);
        }
        return qyCorpInfo.getUrlNumber();
    }
    /**
     * 授权终端
     * @param username
     * @param password
     * @param domain
     * @param authorizationVo
     * @return
     * @throws Exception
     */
    private String auth(String username, String password, String domain, AuthorizationVo authorizationVo) throws Exception {
        HttpHeaders requestHeaders = queryWeiChatService.getHttpHeaders();
        HttpHeaders token = queryWeiChatService.getToken(username, password, domain, requestHeaders);
        if (token == null) {
            return null;
        }
        authorizationVo.setUserName(username);
        return queryWeiChatService.setAuthorizationUser(token, domain, authorizationVo);
    }
}
